#ifndef __HTTP_RESPONSE_H__
#define __HTTP_RESPONSE_H__

#include <string>
#include <vector>
using namespace std;

enum HttpRespField {
	RESP_NONE = 0,
	RESP_ACCEPT_RANGES,
	RESP_AGE,
	RESP_ALLOW,
	RESP_CACHE_CONTROL,
    RESP_CONNECTION,
	RESP_CONTENT_BASE,
    RESP_CONTENT_ENCODING,
    RESP_CONTENT_LANGUAGE,
    RESP_CONTENT_LENGTH,
    RESP_CONTENT_LOCATION,
	RESP_CONTENT_MD5,
    RESP_CONTENT_RANGE,
    RESP_CONTENT_TYPE,
    RESP_DATE,
	RESP_ETAG,
    RESP_EXPIRES,
	RESP_KEEP_ALIVE,
	RESP_LAST_MODIFIED,
	RESP_LINK,   // HTTP/1.0
    RESP_LOCATION,
	RESP_MIME_VER,
	RESP_P3P,
	RESP_PRAGMA,
    RESP_PROXY_AUTH,
	RESP_REFRESH,
    RESP_RETRY_AFTER,
    RESP_SERVER,
	RESP_SET_COOKIE,
	RESP_SET_COOKIE2,
	RESP_TITLE,  // HTTP/1.0
	RESP_TRAILER,
    RESP_TRANSFER_ENCODING,
    RESP_UPGRADE,
	RESP_URI,    // HTTP/1.0
	RESP_VARY,
	RESP_VIA,
	RESP_WARNING,
    RESP_WWW_AUTH,
	RESP_X_ACCELERATED_BY,
	RESP_X_ASPNET_VER,
	RESP_X_CACHE,
	RESP_X_CACHE_LOOKUP,
	RESP_X_PAD,
	RESP_X_PING_BACK,
	RESP_X_POWERED_BY, 
	RESP_X_PSP,
	RESP_X_SERVER,
	RESP_X_TIME,
	RESP_X_UA_COMPAT,
	/*MISC*/
	RESP_OTHER
};

struct RespFieldName {
	HttpRespField field;
	string name;
};

#define HT_MAKE_RESP(r, s) {r, string(s)}

struct OStringRef {
	size_t offset;
	size_t length;
	OStringRef() : offset(0), length(0) {}
	OStringRef(const OStringRef& o) : offset(o.offset),length(o.length){}
	OStringRef(size_t o, size_t l) : offset(o), length(l) {}
};

struct RespFieldValue {
	HttpRespField field;
	OStringRef name;
	OStringRef value;
	RespFieldValue() : field(RESP_NONE), name(), value() {}
	RespFieldValue(const RespFieldValue& rfv) 
		: field(rfv.field), name(rfv.name), value(rfv.value) {}
	RespFieldValue(HttpRespField f, OStringRef n, OStringRef v) 
		: field(f), name(n), value(v) {}
};

enum { 
	CNTLEN_UNKNOWN = -2,
	CNTLEN_CHUNKED = -1,

	CONNECTION_UNKNOWN = 0,
	CONNECTION_CLOSE = 1,
	CONNECTION_KEEP_ALIVE = 2,

	HTTPVER_1_0 = 100,  // HTTP/1.0
	HTTPVER_1_1 = 101,  // HTTP/1.1
};

#define MIN_RESP_LEN 16

class HttpResponse {
public:
	HttpResponse();
	HttpResponse(const char *hbuf, int hlen);
	~HttpResponse();	

	int Parse(const char *hbuf, int hlen);

	int    QueryStatusCode() const;
	string QueryStatusLine() const;
	int    QueryHttpVersion() const;

	string QueryField(HttpRespField field) const;
	string QueryField(const string& field) const;

	int    QueryConnection() const;
	int    QueryContentLength() const;
	string QueryContentType() const;
	string QueryLocation() const;
	string QueryCookie() const;
	int    QueryContentEncoding() const;

	int    GetHeaderLength() const;
	string GetRawHeader() const;

private:
	string m_rawhdr;
	int m_version;
	int m_statuscode;
	vector<RespFieldValue> m_fv;

	typedef vector<RespFieldValue>::iterator field_iterator;
	typedef vector<RespFieldValue>::const_iterator field_const_iterator;
};

#endif //__HTTP_RESPONSE_H__
